package designpatterns.produceconsume.runnable;



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 李栋
 * @version 1.0.0
 * @className WaitNotiFyTest.java
 * @createTime 2021年08月07日 19:36:00
 */
public class TestOne {


    /**
     * 多个线程实现生产者消费者模式
     *
     * @param args
     */

    public static void main(String[] args) {
        CountNum countNum = new CountNum(0);
        String lock = "lock";
        new Thread(new ProduceThread(countNum, lock)).start();
        new Thread(new ConsumeThread(countNum, lock)).start();
        new Thread(new ProduceThread(countNum, lock)).start();
        new Thread(new ConsumeThread(countNum, lock)).start();
    }

}

class ProduceThread implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(String.valueOf(ProduceThread.class));

    private final CountNum countNum;
    private final String lock;

    public ProduceThread(CountNum num, String lock) {
        this.countNum = num;
        this.lock = lock;
    }

    @Override
    public void run() {
        //int num = 0;
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                logger.error(e.getMessage(),e);
            }
            synchronized (lock) {
                if (countNum.getNum() == 10) {
                    try {
                        // 阻塞
                        lock.wait();
                    } catch (InterruptedException e) {
                        logger.error(e.getMessage(),e);
                    }
                } else {
                    countNum.setNum((countNum.getNum()) + 1);
                    logger.info("Thread " + Thread.currentThread().getId() + "生产第：" + countNum.getNum() + "件商品");
                    lock.notifyAll();
                }
            }
        }
    }
}

class ConsumeThread implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(String.valueOf(ConsumeThread.class));

    private final CountNum countNum;
    private final String lock;

    public ConsumeThread(CountNum countNum, String lock) {
        this.countNum = countNum;
        this.lock = lock;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                logger.error(e.getMessage(),e);
            }
            synchronized (lock) {
                while (countNum.getNum() == 0) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        logger.error(e.getMessage(),e);
                    }
                }
                int num = countNum.getNum();
                num--;
                countNum.setNum(num);
                logger.info("Thread " + Thread.currentThread().getId() + "消费第：" + (num + 1) + "件商品");
                lock.notifyAll();
            }
        }

    }
}

